import Draw from "./draw.js";
import { isEmpty, getTransformCoordinate } from "./common.js";

// 创建入口
export default class Flow extends Draw {
  constructor(
    { width, height, highlight, defaultStyle = {}, drag },
    dom,
    checkedCallback
  ) {
    super({ highlightInfo: highlight });
    if (!dom) throw new Error("请指定挂载 DOM ");

    // 默认图案样式
    this.defaultColor = defaultStyle.fillColor || "rgba(0, 0, 0, 1)";
    this.defaultWidth = defaultStyle.lineWidth || 1;

    // 标记点样式
    this.defaultSignStyle = {
      // 缩放框样式
      zoomColor: defaultStyle.zoomColor || "rgb(30, 0, 255)",
      zoomWidth: defaultStyle.zoomWidth || 1,

      // 旋转框样式
      rotateColor: defaultStyle.rotateColor || "rgb(30, 0, 255)",
      rotateWidth: defaultStyle.rotateWidth || 1,

      // 连接线样式
      connectColor: defaultStyle.connectColor || "rgb(19, 154, 251)", // 目前只可使用 fill，不可选 stroke
    };

    // 鼠标点击的回调
    this.checkNodeCallback = () => {};
    if (checkedCallback && typeof checkedCallback === "function")
      this.checkNodeCallback = checkedCallback;

    this.canvas = dom;
    // this.canvas = document.getElementById("drawingBoard");
    this.canvas.width = width;
    this.canvas.height = height;

    this.drag = drag; // 是否开启鼠标拖拽功能
    this.ctx = null; // 绘制图案使用的画布
    this.layer = null; // 实际使用的画布
    this.shadeLayer = null; // 分层画布（对图案进行操作时在这层画布中操作，操作完成后将数据同步至 this.layer 中绘制）
    this.weakMap = new WeakMap();
    if (this.canvas.getContext) {
      if (!this.layer) this.layer = this.canvas.getContext("2d");
    }
    this.ctx = this.layer;
    this.createBackboard(width, height);
    this.load();
  }

  // ******** 👇下面是可供调用的接口 ********

  // 初始化加载
  load() {
    this.canvas.addEventListener("mousedown", (val) => {
      let eventProps = getTransformCoordinate(this.canvas, {
        offsetX: val.offsetX,
        offsetY: val.offsetY,
      });
      this.mousedown(eventProps);
    });
    // this.canvas.addEventListener("keyup", (val) => {
    //   if(val.code === 'Backspace') {
    //     this.deleteNode()
    //   }
    // });
    this.canvas.addEventListener("mouseup", () => {
      // 在没有蒙版的情况下，判断是否选中了图案（存在蒙版的情况下忽略这个监听，因为那时候监听器在蒙版上）
      // * 如果未选中图案，则在这里执行callback
      // * 如果选中了图案，则不在这里执行callback
      if (JSON.stringify(this.getNode()) === "{}") {
        this.checkNodeCallback({});
      }
    });

    this.repaint();
    this.repaintBackboard();
  }

  // 清空所有画布数据
  clearable() {
    this.init();
    this.empty();
  }

  // 重载画布数据
  reload() {
    this.repaint();
  }

  // 删除图形
  delNode(id) {
    this.deleteNode(id);
  }

  // 获取当前选中的元素
  // * 只能供外部使用
  getNode(id) {
    if (typeof id === "object" && String(id) !== "null")
      throw new Error("id should be string");
    let ele;
    if (id) {
      ele = this.canvasInfoMap.get(id);
    } else {
      ele = this.ele || this.connectLineEle || {};
    }
    if (!ele.id) return {};
    Object.assign(ele, this.stagingMap);
    let newEle = JSON.parse(JSON.stringify(ele));
    // 填充数据格式
    if (JSON.stringify(ele) !== "{}") {
      if (typeof newEle.drag !== "boolean") newEle.drag = true;
      if (typeof newEle.unClick !== "boolean") newEle.unClick = false;
      if (typeof newEle.connect !== "boolean") newEle.connect = false;
      if (typeof newEle.zoom !== "boolean") newEle.zoom = false;
    }

    return this.depProxy(newEle, newEle);
  }
  // 响应式数据
  depProxy(newEle, targetEle) {
    let that = this;
    let handler = {
      get(target, key) {
        if (
          JSON.stringify(target) === JSON.stringify(targetEle) &&
          ["fillColor", "lineWidth"].includes(key)
        ) {
          // 由于暂存区存储了第一层的 fillColor, lineWidth，所以需要校验是否为 object 的第一层
          return that.stagingMap[key];
        } else {
          if (target[key] && typeof target[key] === "object") {
            return that.depProxy(target[key], targetEle);
          }
          if (key === "textInfo") {
            // 处理获取的 object 类型字段未定义的情况
            target[key] = {};
            return that.depProxy(target[key], targetEle);
          }
          return target[key];
        }
      },
      set(target, key, value) {
        target[key] = value;
        if (
          JSON.stringify(target) === JSON.stringify(targetEle) &&
          ["fillColor", "lineWidth"].includes(key)
        ) {
          that.stagingMap[key] = value;
        } else if (key === "src") {
          that.imageMap.delete(targetEle.id); // 如果更换了图片路径，则从 imageMap 中清空对应的引用，等待下一次渲染时自动加入
        }
        that.canvasInfoMap.set(targetEle.id, targetEle);
        if (that.highlightEle && targetEle.id === that.highlightEle.id)
          that.highlight(targetEle);
        return true;
      },
    };

    return new Proxy(newEle, handler);
  }

  // 获取画布中所有元素
  // * 只能供外部使用
  getNodes() {
    let res = { nodes: [], connects: this.connectInfo };
    this.canvasInfoMap.forEach((i) => {
      res.nodes.push(i);
    });
    return res;
  }

  // 定义图案类型
  // type: 要绘制的图案类型
  // props: 自定义属性
  /*
    auxProps: 辅助属性
    {
      globalCompositeOperation: '',   // 设置合成的操作类型
    }
  */
  setNodeType(type, props, auxProps) {
    // 限制节点类型
    this.type = type;
    // 自定义属性（只要是 Object 类型均可，需要去除一些内部使用的属性）
    if (props) {
      if (typeof props === "object") {
        this.customProps = JSON.parse(JSON.stringify(props));
        // 剔除内部用到的动态变化的属性
        for (let i of this.validateProp) {
          delete this.customProps[i];
        }
      } else {
        throw new Error("props 需为 object");
      }
    }
    if (typeof auxProps === "object") {
      if (auxProps) {
        for (let i of this.validateAuxProp) {
          if (auxProps[i]) this.auxProps[i] = auxProps[i];
        }
      }
    }
  }

  // 定义连接线类型
  setConnectType(val) {
    this.connectType = val;
  }

  // 绘制自定义图案
  customDrawing(val) {
    this.customDraw(val, true);
  }

  // 添加图案
  addNode(element) {
    if (!element) return;
    let ele = JSON.parse(JSON.stringify(element));
    ele.id = this.getUniqueId(ele.id);
    // 添加默认样式
    if (!ele.fillColor) ele.fillColor = this.defaultColor;
    if (!ele.lineWidth) ele.lineWidth = this.defaultWidth;
    ele.level = isEmpty(ele, "level") ? ele.level : 1;
    let node;
    if (ele.type === "rect") {
      /*
          绘制矩形
          x/y: 开始坐标
          width/height: 宽高
          rotate: 旋转弧度
          fillColor: 填充颜色
          fillType: 类型  fill/stroke
          textInfo: { text:'', font:12px serif, fillType:'fill/stroke', fillColor:'rgba()' }
        */
      node = this.Rect.rect(ele, true, false);
    } else if (ele.type === "circular") {
      /*
          绘制圆形
          x/y: 圆心
          radiusX/radiusY: 半径（长边半径和短边半径）
          startAngle/endAngle: 开始角度和结束角度 ( 默认是 0 ～ Math.PI * 2 )
          rotate: 旋转弧度
          fillColor: 填充颜色
          fillType: 类型  fill/stroke
          textInfo: {text:'', font:12px serif, fillType:'fill/stroke', fillColor:'rgba()'}
        */
      node = this.Circular.circular(ele, true, false);
    } else if (ele.type === "line") {
      /*
          绘制直线
          x/y: 起点,
          endX/endY: 终点,
          fillColor: 填充颜色
          fillType: 类型  fill/stroke
          lineWidth: 宽度
          textInfo: {text:'', font:12px serif, fillType:'fill/stroke', fillColor:'rgba()'}
        */
      node = this.Line.line(ele, true, false);
    } else if (ele.type === "image") {
      /*
          加载图片
          x/y: 起点,
          width/height: 图片宽高,
          rotate: 旋转弧度
          fillColor: 填充颜色
          fillType: 类型  fill/stroke
          textInfo: { text:'', font:12px serif, fillType:'fill/stroke', fillColor:'rgba()' }
        */
      node = this.Rect.rect(ele, true, false);
    } else if (ele.type === "threeCurve") {
      /*
          绘制三次方贝塞尔曲线    * 暂时先不放出来这个方法（后续单独加上曲线的图形）
          x,y: 开始坐标
          x1,y1: 第一组偏移点
          x2,y2: 第二组偏移点
          endX,endY: 终点
          startInfo,targetInfo,start,lineWay,type,textInfo,fillType,lineWidth,fillColor
        */
      // this.threeCurve(ele)
    }
    clearTimeout(this.nodeTimeout);
    this.nodeTimeout = setTimeout(() => {
      this.repaint();
      this.repaintBackboard();
    }, 0);
    return node;
  }

  // 添加连线信息
  addConnect(connect) {
    if (!connect) return;
    try {
      let ele = JSON.parse(JSON.stringify(connect));
      ele.id = this.getUniqueId(ele.id);

      // 验证格式
      if (!ele.startInfo) throw new Error("缺少起始元素信息");
      if (!ele.targetInfo) throw new Error("缺少目标元素信息");

      let start = ele.startInfo;
      let target = ele.targetInfo;
      if (!this.canvasInfoMap.get(start.id)) throw new Error("起始元素不存在");
      if (!this.canvasInfoMap.get(target.id)) throw new Error("目标元素不存在");

      if (!start.pos) throw new Error("起始元素未指定开始位置");
      if (!target.pos) throw new Error("目标元素未指定结束位置");

      if (!ele.type) ele.type = "connectCurve";
      if (!ele.startId) ele.startId = start.id;
      if (!ele.targetId) ele.targetId = target.id;

      this.connectInfo.push(ele);
      this.repaintConnect(ele.id);

      clearTimeout(this.connectTimeout);
      this.connectTimeout = setTimeout(() => {
        this.repaintBackboard();
      }, 10);
    } catch (err) {
      throw new Error(err);
    }
  }
}
